#include "fig_bone_animation.h"
#include "fighter.h"
#include "fig_bonefile_cache.h"
#include "fig_constants.h"  

#include "script/scripthelper.h"

using namespace script;

FIGBoneAnimation::FIGBoneAnimation() : m_CurrentStep(0),
									   m_Rotation(0),
									   m_Radius(0.01f)
{
	m_Pos = math::Vec2(-1.0f,-1.0f);			// offscreen first before it got initialized
	m_Color = ColorfRGBA(1.0f,1.0f,1.0f,1.0f);
}

void		FIGBoneAnimation::Render(const math::Vec2& Offset,float Scale)
{
   if( (int)m_AnimatinSteps.size() - 1 < m_CurrentStep)
		return;

	FIGBoneAnimation::AnimationStep* pAnimationStep = m_AnimatinSteps[m_CurrentStep];
	
	for(int i = 0; i < (int)pAnimationStep->m_pAnimationParts.size(); i++)
	{
		FIGBoneAnimation::AnimatonPart* pAnimationPart = pAnimationStep->m_pAnimationParts[i];
		if(pAnimationPart->m_pBonePart == NULL)
			continue;

		FIGBonePart*		pBodyPart = pAnimationPart->m_pBonePart;
		pBodyPart->Render(
							m_Pos + Offset ,
							Scale, 
							m_Rotation, 
							m_Color);

		
	}
}

FIGBoneAnimation::~FIGBoneAnimation()
{
	
   for(int i = 0; i < (int)m_BoneParts.size(); i++)
   {
		FIGBonePart* pBodyPart = m_BoneParts[i];		
		UTIL_SAFE_DELETE(pBodyPart);
   }
   m_BoneParts.resize(0);

   for(int i = 0; i < (int)m_AnimatinSteps.size(); i++)
   {
		AnimationStep * pAni = m_AnimatinSteps[i];
		pAni->Clear();
		UTIL_SAFE_DELETE(pAni);
   }
   m_AnimatinSteps.resize(0);

   /*
   this waypoints is not ours
   for(int i = 0; i < (int)m_WayPoints.size(); i++)
   {
		WayPoint * pWP = m_WayPoints[i];
		UTIL_SAFE_DELETE(pWP);
   }
   */
   m_WayPoints.resize(0);

   

}

void		FIGBoneAnimation::Reset()
{
	m_Pos = math::Vec2(-1.0f,-1.0f);			// offscreen first before it got initialized
	m_CurrentStep = 0;
	for(int i = 0; i < (int)m_BoneParts.size(); i++)
	{
		FIGBonePart* pBodyPart = m_BoneParts[i];
		pBodyPart->Reset();
    }
}


void		FIGBoneAnimation::RenderShadow(const math::Vec2& Offset,float Scale)
{

	if( (int)m_AnimatinSteps.size() - 1 < m_CurrentStep)
		return;

	FIGBoneAnimation::AnimationStep* pAnimationStep = m_AnimatinSteps[m_CurrentStep];
	
	for(int i = 0; i < (int)pAnimationStep->m_pAnimationParts.size(); i++)
	{
		FIGBoneAnimation::AnimatonPart* pAnimationPart = pAnimationStep->m_pAnimationParts[i];
		if(pAnimationPart->m_pBonePart == NULL)
			continue;

		FIGBonePart* pBodyPart = pAnimationPart->m_pBonePart;
		pBodyPart->Render(m_Pos + Offset + math::Vec2(-m_Radius,m_Radius),Scale, m_Rotation, m_Color);
		
	}
}


void		FIGBoneAnimation::SetColor(float R,float G,float B,float A)
{
	m_Color = ColorfRGBA(R,G,B,A);
}


FIGBonePart*		FIGBoneAnimation::AddBonePart(
														  int ID,
														  const std::string& Name,
														  float X,
														  float Y , 
														  float Rotation
														  )
{
	FIGBonePart* pBodyPart;
	pBodyPart= new FIGBonePart(ID,Name,X,Y,Rotation);
	m_BoneParts.push_back(pBodyPart);
	return pBodyPart;    
}


FIGBonePart*		FIGBoneAnimation::GetBonePartByID(int ID)
{
   for(int i = 0; i < (int)m_BoneParts.size(); i++)
   {
		FIGBonePart* pBodyPart = m_BoneParts[i];
		if(	ID == pBodyPart->GetID())
			return pBodyPart;
   }
   return NULL;
}



bool	FIGBoneAnimation::TransformBackwardTick(float dt)
{
	const int BACKWARD = -1;
	return TransformTick(dt,BACKWARD);	
}

bool	FIGBoneAnimation::TransformForwardTick(float dt)
{
	const int FORWARD = 1;
	return TransformTick(dt,FORWARD);	
}


bool			FIGBoneAnimation::TransformTick(float dt,int Dir)
{
    bool RetVal = true;
	if(m_AnimatinSteps.size() <= 0)
		return RetVal;
    FIGBoneAnimation::AnimationStep* pAnimationStep = m_AnimatinSteps[m_CurrentStep];
	
	for(int i = 0; i < (int)pAnimationStep->m_pAnimationParts.size(); i++)
	{
		FIGBoneAnimation::AnimatonPart* pAnimationPart = pAnimationStep->m_pAnimationParts[i];
		if(pAnimationPart->m_pBonePart == NULL)
			continue;

		
		
		bool Finish = pAnimationPart->m_pBonePart->Transform(
												dt,
												pAnimationPart->m_Pos,
												(pAnimationPart->m_Pos - pAnimationPart->m_pBonePart->GetPosBackup()) * 2.0f
												);

		if(!Finish)
		  RetVal = false;
		float RotationSpeed = pAnimationPart->m_Rotation - pAnimationPart->m_pBonePart->GetRotationBackup();
		if(RotationSpeed < 0)
			RotationSpeed *= -1;

		while(RotationSpeed > 360.0f)
		{
			RotationSpeed -= 360.0f;
		}


		if(RotationSpeed > 0)
		{
			if(RotationSpeed > 180.0f)
				RotationSpeed = 360 - RotationSpeed;
			Finish = pAnimationPart->m_pBonePart->Transform(
												dt,
												pAnimationPart->m_Rotation,
												RotationSpeed * 2.0f		// half a scond by multiplying with 2.0f
												);
		}

		if(!Finish)
		  RetVal = false;
	}

	if(RetVal)
	{
		m_CurrentStep += Dir;
	
		if(Dir > 0) // forward
		{
			if(m_CurrentStep >= (int)m_AnimatinSteps.size())
			{
				m_CurrentStep = (int)m_AnimatinSteps.size() -1;
				return true;
			}
		}
		else if ( Dir < 0)	// Backward
		{
			if(m_CurrentStep < 0)
			{
				m_CurrentStep = 0;
				return true;
			}	
		}

	}

	return false;
}


void		FIGBoneAnimation::CopyToBackup()
{
	if(m_AnimatinSteps.size() <= 0)
		return;

    FIGBoneAnimation::AnimationStep* pAnimationStep = m_AnimatinSteps[m_CurrentStep];	
	for(int i = 0; i < (int)pAnimationStep->m_pAnimationParts.size(); i++)
	{
		FIGBoneAnimation::AnimatonPart* pAnimationPart = pAnimationStep->m_pAnimationParts[i];
		if(pAnimationPart->m_pBonePart == NULL)
			continue;

		FIGBonePart* pBodyPart = pAnimationPart->m_pBonePart;
		pBodyPart->CopyToBackup();
	}
}


math::Vec2		FIGBoneAnimation::Load(const std::string& File)
{
	m_File = File;
	math::Vec2 Size;

	FIGBoneFileCache::BoneFileData* pBoneFileData = FIGBoneFileCache::Instance().GetBoneFileDataByFileName(File);
	if(!pBoneFileData)
		return Size;
	
	m_BonePartFileNames.resize(0);
	for(int i =0; i < (int)pBoneFileData->m_BoneDatas.size(); i++)
	{
		m_BonePartFileNames.push_back(pBoneFileData->m_BoneDatas[i]->Name);
		AddBonePart(pBoneFileData->m_BoneDatas[i]->ID,
					pBoneFileData->m_BoneDatas[i]->Name,
					0,
					0,
					0);
	}	
	//--------------------------

	
	for(int i =0; i < (int)pBoneFileData->m_AnimationDatas.size(); i++)
	{
		FIGBoneAnimation::AnimationStep* pAnimationStep = new FIGBoneAnimation::AnimationStep();
		m_AnimatinSteps.push_back(pAnimationStep);
		FIGBoneFileCache::AnimationData* pAnimationData = pBoneFileData->m_AnimationDatas[i];
		for(int j =0; j < (int)pAnimationData->m_AnimationPartDatas.size(); j++)
		{
			FIGBoneFileCache::AnimationPartData* pAnimationPartData =  pAnimationData->m_AnimationPartDatas[j];
			FIGBonePart* pBonePart = GetBonePartByID(pAnimationPartData->ID);
			
			FIGBoneAnimation::AnimatonPart* 
				pAnimatinPart = new	FIGBoneAnimation::AnimatonPart(
																	pBonePart,
																	pAnimationPartData->CenterRelative,
																	pAnimationPartData->Rotation
																		);

			pBonePart->Init(pAnimationData->m_AnimationPartDatas[j]->CenterRelative,
							pAnimationData->m_AnimationPartDatas[j]->Rotation);			
			pAnimationStep->m_pAnimationParts.push_back(pAnimatinPart);

		}

	} 

	for(int i = 0; i < (int)m_BoneParts.size(); i++)
	{
			FIGBonePart* pBodyPart = m_BoneParts[i];
			if(	Size.x < pBodyPart->GetSize().x)
				Size.x = pBodyPart->GetSize().x;
			if(	Size.y < pBodyPart->GetSize().y)
				Size.y = pBodyPart->GetSize().y;
				
	}
	//-------------------

	
	for(int i =0; i < (int)pBoneFileData->m_pWPs.size(); i++)
	{	    		
		m_WayPoints.push_back(pBoneFileData->m_pWPs[i]);
	}
	
   
   return Size;
}

math::Vec2			FIGBoneAnimation::GetPosByWayPoint(int Index)
{
	math::Vec2 Pos;

	


	if(Index < (int)m_WayPoints.size())
	{
		math::Vec2 Temp = m_WayPoints[Index]->m_Pos;
		//const float Scale = Fighter::Instance().GetScale();
		//Temp.y +=  ( GraphicsUtil::HEIGHT * ( 1024.0f / 960.0f)) ; 
		return Temp;
	}

	return Pos;
}


